home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Precision Software Appli…tions Silver Collection 1
/
Precision Software Applications Silver Collection Volume One (PSM) (1993).iso
/
tutor
/
modula12.exe
/
CHAP3.TXT
< prev
next >
Wrap
Text File
|
1988-10-26
|
30KB
|
652 lines
Chapter 3 - The simple Modula-2 data types
The material in this chapter is extremely important to
you as you strive to become a good Modula-2 programmer, but
you may also find it to be somewhat tedious because it
contains so many facts. This material is needed in order to
develop the topics in the next few chapters, but all of the
details are not necessarily required. For that reason, you
may wish to go through it rather rapidly picking up the high
points and come back to this chapter for the details later
when they will be much more meaningful. Do not completely
pass over this material at this time or the next few
chapters will be meaningless unless you are already highly
experienced in other programming languages.
A PROGRAM WITH VARIABLES
Load and display the program named INTVAR.MOD for our
first program with some variables in it. This program
begins in the usual way since it has a MODULE header and the
IMPORT list. Next we come to a new reserved word, VAR.
This word is used to indicate to the compiler that we wish
to define one or more variables. In Modula-2, there is a
rule that says you can use nothing until it is defined. If
we wish to use a variable in the program, we must first
define that it will exist, and what kind of a variable it
is. After that, it can be used in the program to do what
needs to be done.
Following the reserved word VAR, we have the variable
named "Count" defined. The reserved word INTEGER following
the colon states that the variable "Count" will be of type
INTEGER. This means that it can store any whole number
between -32768 to 32767. Don't worry too much about this
yet, the next program will completely define what an INTEGER
type variable is. It is important to recognize that after
we have defined the variable "Count", it still doesn't have
a value stored in it, that will come later.
The next line has two more variables defined, namely
"x", and "y". They are also INTEGER type variables and do
not have a value stored in them yet. You can think of the
three variables as three empty boxes, each capable of
storing a number but with no number in them yet. It would
be perfectly permissible to put all three variables on one
line, or to have separated them such that each was on a
separate line. At this point, the program doesn't know that
there is any difference between them, because there isn't
any. The fact that one will contain the sum of the other
two has no meaning yet, the comments are only for us, not
the computer.
Page 13
Chapter 3 - The simple Modula-2 data types
USING VARIABLES IN A PROGRAM
Now we will go to the program itself. The first line
sets the variable "x" equal to 12, in effect putting the
number 12 in the box mentioned earlier. The sign := is the
Modula-2 symbol for assignment. It is most meaningful to
read the symbol "gets the value of" since it is not really
stating a mathematical equality but is saying in effect,
"assign the value of this to the variable at the left." The
entire line can be read as "x gets the value of 12." There
is now a value assigned to the variable "x" declared in the
header. The next statement assigns the value of 13 to the
variable "y". Finally the value of the data stored in the
variable "x" is added to the value of the data stored in the
variable "y", and the sum is stored in the variable "Count".
We have therefore done our first calculations in Modula-2
but we will do many more before this tutorial is completed.
Notice that each statement is terminated with a
semicolon, a Modula-2 requirement.
The three variables are then displayed on the monitor
with appropriate prose to identify them. The only new
statement here is the "WriteInt" procedure that needs a
little explanation. This procedure is used to output an
INTEGER type variable to the monitor or whatever device is
being used. By definition, it contains two quantities
within the parentheses, the variable name and the number of
columns it should fill. If there are not enough columns to
output the data, more will be used so that no digits will be
truncated. If all are not needed, leading blanks will be
output. If the variable "x" had the value of 1234 when we
came to program line 18, all four digits would be output in
spite of the request for three. Since "x" has the value of
12, only two columns will be used and one leading blank will
be output. In like manner, "y" is allotted 4 columns and
"Count" is to be output in 6 columns.
The last two lines of the program assign new values to
two of the variables. The variable "x" is assigned the
value of FF hexadecimal which is 256 decimal, and "y" is
assigned the value of 177 octal which is 127 decimal. This
is only done as an illustration to you of how it is done. If
you don't understand these two numbering systems, simply
ignore this until you have a need for it.
Compile and run this program to see if it does what you
expect it to do. The important thing to notice in this
program is the variable definition in the definition part of
the module and the variable assignment in the program part.
It should be obvious, but it would be well to mention that
Page 14
Chapter 3 - The simple Modula-2 data types
the definition part of the module extends from the module
name to the reserved word "BEGIN" and is where all
definitions are put. Likewise, the program part of the
module includes all statements from the "BEGIN" to the
"END".
SIMPLE VARIABLE TYPES
Modula-2 has several predefined data types that you can
use in your programs. You also have the ability to define
any number of complex types built up from the simple types
but we will not discuss this until we get to chapter 6 and
beyond. The simple types are INTEGER, CARDINAL, REAL,
BOOLEAN, and CHAR. Each has its own purpose and its own
peculiarities and we will cover each type one at a time.
THE SIMPLE VARIABLE - INTEGER
Load and display the program named INTMATH.MOD for an
example of INTEGER math. In the declaration part of the
program (the part prior to the BEGIN) we have 7 INTEGER type
variables defined for use in the program. We will use them
to illustrate INTEGER arithmetic.
An INTEGER variable, by definition, can store any whole
number between -32768 and 32767. An attempt to store any
other value in an INTEGER type variable should produce an
error by your compiler but it may produce some other result.
Some compilers may store a -32769, which is one count too
low, as a 32767 which is at the top end of the range. This
is due to the two's complement arithmetic that you don't
need to understand at this point. It will be left to you to
determine what your compiler does in such a case.
The first line in the program is nothing new to you, it
simply assigns the variable "A" the value of 9. The second
line adds 4 to the value stored in the variable "A" and the
result, 13, is stored in the variable "B". Next the values
stored in the variables "A" and "B" are added together and
the sum, which is 9 + 13, is stored in the variable
"IntSum". Continuing in the same manner, the difference and
the product are calculated and stored. When we come to
INTEGER division, we are breaking new ground because the
result is truncated to the largest whole number resulting
from the division. Thus 13 DIV 9 results in 1 because the
remainder is simply dropped. The next construct, B MOD A
results in the remainder of the division, in this case 4.
You will find these operations very useful as you progress
as a Modula-2 programmer.
Page 15
Chapter 3 - The simple Modula-2 data types
The intent of the next line is to illustrate that you
can do several math operations in a statement if you are
careful to put the parentheses in the proper places. There
are definite rules about operator precedence but I recommend
that you use lots of parentheses to remove all doubt as to
what the results will be.
The results of the operations are displayed in 6
columns and we move on to several new operations. The first
new operation is the "INC" which is short for "increment".
This simply increments the variable contained within the
parentheses and if a second argument is given, the variable
is incremented by the value of that variable. In like manner
the "DEC" procedure decrements the variable in the
parentheses by one unless a second argument is given in
which case the variable is decremented by the value of that
variable.
It may not be clear at this point, but the second
variable itself may be another variable name or even a
composite of several as long as it results in an INTEGER
type variable. This is illustrated in the program.
Finally, we come to the last two procedures in this
program, the "MIN" and the "MAX". These two procedures will
return the value of the smallest possible INTEGER, -32768
and the largest possible INTEGER, 32767. These are the
values returned for a 16 bit microcomputer which is what you
are probably using since that is what this tutorial is
intended for. It would be well to add that not all Modula-2
compilers implement these functions so you may need to
comment out these two lines in order to compile and run this
program.
Compile and run this program and observe the output.
If your compiler results in errors, you may have to make
some changes in order to compile it. Refer to the
COMPILER.DOC file on the distribution disk for notes on some
of the more popular Modula-2 compilers.
THE SIMPLE VARIABLE - CARDINAL
Load and display the file named CARDMATH.MOD for an
example of CARDINAL mathematics and output. In this file, 7
variables are defined as CARDINAL and one more as INTEGER. A
CARDINAL variable can store any whole number from 0 to 65535
in a 16 bit microcomputer, although the range may be
different if you are using an unusual computer or compiler.
The first few lines are the same as the last program so
very little needs to be said about them except for the
Page 16
Chapter 3 - The simple Modula-2 data types
subtraction example. In this case, the result of the
subtraction would be negative if it were carried out as in
the last program so "A" is subtracted from "B". It is an
error to attempt to store a negative number in a CARDINAL
type variable. For that reason, a CARDINAL should not be
used if there is any chance that it will be required to go
negative. Programming experience will be the best teacher
when it comes to deciding what variables to use in each
situation.
In this program the variables are once again displayed,
but now the procedure named "WriteCard" is used for output
because the variables to output are CARDINAL.
The next two statements indicate that INTEGER and
CARDINAL variables are "assignment compatible" meaning that
they can be assigned to each other with the := operator.
They cannot however, be mixed in calculations. Constants in
an expression are assumed to be of the same type as the
variables in the expression and they must agree. For that
reason, the expression in line 36 is invalid because (-112)
is required to be a CARDINAL constant but it is negative and
therefore not CARDINAL. In the prior line it is permissible
to subtract 112 from the value of "A" as long as the result
is still positive. As an exercise, change line 34 such that
a number less than 112 is assigned to "A". The program will
compile without error but when you run it, you should get a
runtime error because the CARDINAL assignment is out of
range. Notice that the constant value of -112 is allright
for use an an INTEGER variable.
The remaining statements in the program are the same as
the last program so additional explanation is unneeded. It
would be good to point out that in the case of CARDINAL, the
"MIN" and "MAX" procedures will return values of 0 and
65535 for most 16 bit implementations.
Compile and run this program remembering that it may be
necessary to comment out the "MIN" and "MAX" statements to
get a successful compilation.
THE SIMPLE VARIABLE - REAL
Load and display the program named REALMATH.MOD for a
demonstration of the data type REAL. The definition part of
this program is similar to the last with some additions to
the IMPORT list. Your compiler may use different names for
some of the procedures here, so if you get a compile error
you will need to modify these. We will study the IMPORT
(and EXPORT) list in detail later, so be patient.
Page 17
Chapter 3 - The simple Modula-2 data types
Several REAL variables and one each of the INTEGER and
CARDINAL types are defined for use in the program. The REAL
type variable can contain numbers in a wide range and with
fractional parts included. The exact range, and the
accuracy will vary widely depending on your implementation.
It will be up to you to check your reference manual for the
limits on your computer and compiler. A REAL type number is
defined as one with a decimal point. The mathematics are
the same as with the other two except that the division
symbol is the slash (/). There is no "MOD" for REAL type
numbers because there is theoretically no remainder, since a
fractional part is computed as part of the calculation.
The four results are displayed on the monitor with 12
columns allowed for each result and two extra blanks
displayed between each number. Unfortunately, we have no
control over how many digits will be displayed following the
decimal point. This would be nice for outputting data in a
financial model where we would like to have two digits
following the decimal point. When we get to the advanced
part of this tutorial, we will write our own procedure for
doing that in such a way that we can call it from any
program just like we call these output procedures.
CONVERSION BETWEEN DATA TYPES
Beginning in line 37, we assign the INTEGER and
CARDINAL variables some values and convert the values to
type REAL by using the procedure "FLOAT". We then convert
the variable "Sum" to INTEGER and CARDINAL by use of the
procedure "TRUNC". The fractional part, if any, will simply
be thrown away. These procedures will be very useful in
many of your programs.
The last two lines return the value of the largest
possible REAL number and the smallest REAL number for your
implementation. Once again, your compiler may not support
these two functions and they may have to be commented out in
order to compile.
Compile and run this program.
THE SIMPLE VARIABLE - BOOLEAN
Load and display the file named BOOLMATH.MOD on your
monitor for an example of BOOLEAN variables. A BOOLEAN
variable can only have one of two possible values, TRUE or
FALSE. These variables cannot be printed directly but can
be used to control other print statements to print out a
representation of their value. We will see how later.
Page 18
Chapter 3 - The simple Modula-2 data types
We define 3 BOOLEAN variables and 3 INTEGER variables
and assign values to the 3 INTEGER variables in the program
for use in these illustrations. In line 13 the BOOLEAN
expression "A = 22" is TRUE, therefore the BOOLEAN variable
"IsIt" is assigned the value TRUE. The variable "IsIt"
could be used later in the program to make a decision, by a
yet undefined method, to do something or bypass it. In like
manner, the next statement assigns "IsIt" the value FALSE
because A is not equal to 23. The remainder of the allowed
BOOLEAN expressions are defined in the next few lines and
are left for your inspection and study.
Beginning in line 25, composite BOOLEAN expressions are
illustrated. As many BOOLEAN expressions as desired can be
combined with AND and OR operators. If two or more BOOLEAN
expressions are combined with the AND, the result is TRUE if
all expressions are TRUE. If two or more BOOLEAN
expressions are combined with the OR, the result is true if
any of them are TRUE. The NOT operator inverts the sense of
what it modifies, it turns a TRUE to FALSE and vice-versa.
Finally a couple of composite BOOLEAN expressions are given
for illustration of the amount of complexity that is
allowed, although there is no real limit as to how far you
can go with the complexity. Good programming practice would
dictate that you keep it simple and understandable.
TWO RULES FOR BOOLEAN EVALUATION
First it is important that you use the same type of
variables within a BOOLEAN expression. REAL's can be
compared to REAL's and INTEGER's to INTEGERs, but REAL's
cannot be compared to INTEGER's. CARDINAL and CHAR types
can also be compared to their own types, but none of the
four can be compared directly to each other.
Secondly, Modula-2 uses a shortcut evaluation technique
for BOOLEAN evaluation. Evaluation proceeds from left to
right and if it finds a result which will positively
determine the outcome, evaluation stops. For example, if it
is evaluating a string of 5 comparisons all combined with an
AND, and it finds that the second term is FALSE, evaluation
stops there. Since all terms must be TRUE for the result to
be TRUE, it makes no difference what values the last three
are, the result will be FALSE because of the second term.
THE SIMPLE VARIABLE - CHAR
Load and display the program named CHARDEMO.MOD for an
illustration of the last simple variable type, CHAR. Text
data is stored in a computer in a format utilizing the CHAR
data type. Although there are exceptions, such as when text
Page 19
Chapter 3 - The simple Modula-2 data types
is stored in some form of a packed mode, this is nearly
always true. This tutorial was written with a word
processor that uses a CHAR type for text storage, and few
word processors use any other method.
Although there are many different ways to store text,
only two are used to any level of significance, EBCDIC and
ASCII. ASCII is used almost exclusively in micro computers.
I have never heard of an implementation that used EBCDIC in
a microcomputer, so we will limit our discussion to ASCII.
This merely refers to the way the characters of the alphabet
and all other characters are represented in the computer.
The ASCII standard defines that the value of 65 will be the
letter 'A', 66 will be the letter 'B', etc. If everyone
uses the same standard, transfer of data from one computer
to another is greatly simplified.
The program named CHARDEMO has the usual header with 4
CHAR type variables defined for use in the program. An
INTEGER is also defined. In the program itself, we begin by
assigning 2 of the variables some CHAR data. Since a CHAR
variable is capable of storing one letter, numeral, or
special character, each variable is assigned one letter.
The single or double quotes are used as an indication to the
compiler that you intend for it to use the letter as a CHAR
type variable rather than as another variable name. Of
course if you wanted to use "A" as a variable name, you
would have to define it in the definition part of the
module.
TWO SPECIAL CHAR PROCEDURES
The next instruction gets the ordinal value of the
letter "A", adds two to it, and assigns that value to the
variable "Index", which must be an INTEGER (although it
could have been defined as a CARDINAL). Refer to the
documentation that came with your computer and you will find
an ASCII table that will define the letter "A" as 65.
Finally, the CHAR type variable "Dog3" is assigned the
character value of "Index". Your ASCII table should define
67 as the letter "C". It is important to understand that
the CHAR variable "Dog3" contains the character
representation of the letter "C", and the INTEGER variable
"Index" contains the numerical value of the ASCII
representation of the letter "C". It would be perfectly
allright to use the variable "Index" for any desired
numerical calculations, but not to display the letter "C".
On the other hand, it would be allright to use the variable
"Dog3" to display the letter "C" on the monitor but it could
not be used for any calculations. The purpose therefore, of
the two procedures "ORD" and "CHR", is to translate from one
Page 20
Chapter 3 - The simple Modula-2 data types
type to the other.
The variable "Cat4" is assigned the double quote by
enclosing it in the single quotes, and the characters are
output in a funny order to spell "CAT. The variable "Char1"
is assigned the value "S", and the word is completed
resulting in the full word "CATS" on the monitor after the
program is compiled and run.
If this were the only way to use the CHAR type variable,
it would be very tedious and frustrating, but there are
other methods to use the CHAR type that are far more useful
as you will see.
Next, an additional means of assigning a CHAR type
variable is given. By assigning the CHAR variable "65C", it
is the same as writing CHR(65), resulting in the variable
having the internal value "A". A number less than 256
followed by a "C" is defined by Modula-2 as a CHAR type
constant.
Finally, the variable "Char1" is assigned the letter
"a" and it is converted to upper case "A" with the procedure
CAP. This procedure will convert the argument to its upper
case equivalent if it is a lower case letter. If its
argument is an upper case letter or any other character, it
will do nothing to it.
Compile and run this program and observe the output.
USING THE TRANSFER PROCEDURES
Load and display the file named TRANSFER.MOD for
several examples of transferring data between the various
simple data types. The transfer functions given here may
not seem too important at this time, but some time spent
here will help to reduce the frustration later when you get
seemingly wrong errors that say you are using incompatible
types in a statement. All of the program will not be
discussed, only those statements that use some of the more
unusual capabilities of Modula-2.
In line 13, the calculations are done in INTEGER
format, but due to the assignment compatibility of INTEGER
and CARDINAL, the result is converted to CARDINAL across the
":=". Line 16 is an illustration of mixed mathematics using
the transfer procedure INTEGER. Line 20 is the first
example of "nested" procedures which must be done because
FLOAT only uses a CARDINAL for an argument.
Page 21
Chapter 3 - The simple Modula-2 data types
The expression in line 22 is an error because TRUNC
results in a CARDINAL which cannot be added to an INTEGER.
Either of the next two lines fix the problem by making the
addition type-compatible then making use of the assignment
compatibility between INTEGER and CARDINAL for line number
23. The same error occurs in line 26 and is fixed the same
way in either of the next two lines. Once again, in line
31, the incompatible type error occurs and is fixed in
either of two ways in the next two lines.
Lines 35 and 36 illustrate converting CHAR data to
first CARDINAL then REAL which requires nested procedure
calls. The last line of the program is a nest of procedures
which converts a character from CHAR to CARDINAL, then to
REAL, back to CARDINAL, and finally back to the original
CHAR variable. It does nothing except act as a good
illustration to you of what can be done.
Conversion between types is very important. You will
use these techniques often so it is important to know how
they work. A very simple yet helpful memory aid is to
remember that any simple type can be converted to CARDINAL
and CARDINAL can be converted to any type. Most other
conversions require two steps to get from one to the other.
Chapter 14 will readdress this topic with even more
extensive type transfer procedures.
PROGRAMMING PROBLEMS
1. Write a program in which you define, using the CHAR
type variable, the letters "a" and "z", and the numbers
"0" and "9". Convert them to CARDINAL, and display the
four characters and their ASCII (numerical) values.
2. Write a program that you can easily modify to experiment
with conversions between the various types that result in
incorrect conversions to see the results on your compiler.
For example, convert a -1 as an INTEGER to a CARDINAL.
Page 22